{
 "cells": [
  {
   "cell_type": "markdown",
   "id": "2652cd19",
   "metadata": {},
   "source": [
    "# numpy多维数组解释--线性代数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 2,
   "id": "1883ccd1",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[1 2 3 4]\n"
     ]
    }
   ],
   "source": [
    "import numpy as np\n",
    "A = np.array([1, 2, 3, 4])\n",
    "print(A)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 3,
   "id": "51724d89",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "1"
      ]
     },
     "execution_count": 3,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ndim(A) # 维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 4,
   "id": "cc2a94cc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(4,)"
      ]
     },
     "execution_count": 4,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.shape # 形状，返回和多维数组的情况下一致的结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 5,
   "id": "dd2f7509",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "4"
      ]
     },
     "execution_count": 5,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.shape[0] # 返回一维的形状，个人理解形状表示各个维度（这里维度指张量的维度）的向量的维度"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 6,
   "id": "672dd12d",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[[1 2]\n",
      " [3 4]\n",
      " [5 6]]\n"
     ]
    }
   ],
   "source": [
    "B = np.array([[1,2], [3,4], [5,6]])\n",
    "print(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 7,
   "id": "1287965b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "2"
      ]
     },
     "execution_count": 7,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.ndim(B)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 8,
   "id": "0e590898",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 2)"
      ]
     },
     "execution_count": 8,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 9,
   "id": "6829b4ff",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 2)"
      ]
     },
     "execution_count": 9,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.array([[1,2], [3,4]])\n",
    "A.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 10,
   "id": "a1eb7011",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 2)"
      ]
     },
     "execution_count": 10,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = np.array([[5,6], [7,8]])\n",
    "B.shape"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6fdc5cb0",
   "metadata": {},
   "source": [
    "# 多维数组（张量）的乘积"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 11,
   "id": "b2ad1b93",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[19, 22],\n",
       "       [43, 50]])"
      ]
     },
     "execution_count": 11,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(A, B) # 矩阵相乘，A_2x2 · B_2x2 = C_2x2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 15,
   "id": "27a9f348",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 3)"
      ]
     },
     "execution_count": 15,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.array([[1,2,3], [4,5,6]])\n",
    "A.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 16,
   "id": "60a548de",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 2)"
      ]
     },
     "execution_count": 16,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = np.array([[1,2], [3,4], [5,6]])\n",
    "B.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 17,
   "id": "7057b18c",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[22, 28],\n",
       "       [49, 64]])"
      ]
     },
     "execution_count": 17,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(A, B) # A_2x3 · B_3x2 = C_2x2"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 18,
   "id": "e0602a67",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 2)"
      ]
     },
     "execution_count": 18,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "C = np.array([[1,2], [3,4]])\n",
    "C.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 19,
   "id": "5d3be769",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2, 3)"
      ]
     },
     "execution_count": 19,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 14,
   "id": "20eb5bdd",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([[ 7, 10],\n",
       "       [15, 22]])"
      ]
     },
     "execution_count": 14,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(A, C) # A_2x3 · C_2x2 出错，乘不了"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 20,
   "id": "86eb6cb4",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(3, 2)"
      ]
     },
     "execution_count": 20,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "A = np.array([[1,2], [3, 4], [5,6]])\n",
    "A.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 21,
   "id": "5239185b",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "(2,)"
      ]
     },
     "execution_count": 21,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "B = np.array([7,8])\n",
    "B.shape"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 22,
   "id": "c26534bc",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([23, 53, 83])"
      ]
     },
     "execution_count": 22,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.dot(A, B) # 广播B，其实就是常数与矩阵相乘的运算"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ca3029c",
   "metadata": {},
   "source": [
    "# 三层神经网络的计算"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "6cd3c1db",
   "metadata": {},
   "source": [
    "# 单独的例子 $$ a^{(1)}_1 = w^{(1)}_{11}x_1 + w^{(1)}_{12}x_2 + b^{(1)}_1 $$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "48141a96",
   "metadata": {},
   "source": [
    "### 对于$ w^{(1)}_{12} $，上面的（1）指权重，下面的12指上一层的第二个神经元传送给下一层的第一个神经元"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "c99821ff",
   "metadata": {},
   "source": [
    "# 矩阵形式 $$ A^{(1)} = XW^{(1)} + B^{(1)} $$"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "3ef51c46",
   "metadata": {},
   "source": [
    "# $$A^{(1)} = \\begin{pmatrix} a^{(1)}_1 & a^{(1)}_2 & a^{(1)}_3 \\end{pmatrix}, X = \\begin{pmatrix} x_1 & x_2 \\end{pmatrix}, B^{(1)} = \\begin{pmatrix} b^{(1)}_1 & b^{(1)}_2 & b^{(1)}_3 \\end{pmatrix}, W^{(1)} = \\begin{pmatrix} w^{(1)}_{11} & w^{(1)}_{21} & w^{(1)}_{31} \\\\ w^{(1)}_{12} & w^{(1)}_{22} & w^{(1)}_{32} \\end{pmatrix} $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 24,
   "id": "139e2541",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(2, 3)\n",
      "(2,)\n",
      "(3,)\n"
     ]
    }
   ],
   "source": [
    "X = np.array([1.0, 0.5])\n",
    "W1 = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])\n",
    "B1 = np.array([0.1, 0.2, 0.3])\n",
    "\n",
    "print(W1.shape)\n",
    "print(X.shape)\n",
    "print(B1.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 28,
   "id": "d314cc0a",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.3 0.7 1.1]\n",
      "[0.57444252 0.66818777 0.75026011]\n"
     ]
    }
   ],
   "source": [
    "def sigmoid(x):\n",
    "    return 1 / (1 + np.exp(-x))\n",
    "A1 = np.dot(X, W1) + B1\n",
    "Z1 = sigmoid(A1)\n",
    "print(A1) # A为第一层的输入\n",
    "print(Z1) # Z为第一层的输出"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "ca085b4d",
   "metadata": {},
   "source": [
    "# 现第1层到第2层的信号传递"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 29,
   "id": "d40f2d62",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "(3,)\n",
      "(3, 2)\n",
      "(2,)\n"
     ]
    }
   ],
   "source": [
    "W2 = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])\n",
    "B2 = np.array([0.1, 0.2])\n",
    "print(Z1.shape)\n",
    "print(W2.shape)\n",
    "print(B2.shape)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 33,
   "id": "e27d76fe",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.51615984 1.21402696]\n",
      "[0.62624937 0.7710107 ]\n"
     ]
    }
   ],
   "source": [
    "A2 = np.dot(Z1, W2) + B2\n",
    "Z2 = sigmoid(A2)\n",
    "print(A2) # A为第二层的输入\n",
    "print(Z2) # Z为第二层的输出"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "af2cd7d6",
   "metadata": {},
   "source": [
    "# 最后是第2层到输出层的信号传递，注意隐藏层不同"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 37,
   "id": "9f1bdb9b",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.31682708 0.69627909]\n",
      "[0.31682708 0.69627909]\n"
     ]
    }
   ],
   "source": [
    "def identity_function(x):\n",
    "    return x\n",
    "\n",
    "W3 = np.array([[0.1, 0.3], [0.2, 0.4]])\n",
    "B3 = np.array([0.1, 0.2])\n",
    "A3 = np.dot(Z2, W3) + B3\n",
    "Y = identity_function(A3) # 或者Y = A3\n",
    "print(A3) # A为第三层的输入\n",
    "print(Y) # Y为第三层的输出"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d1748cf0",
   "metadata": {},
   "source": [
    "# 小结"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 38,
   "id": "82892302",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.31682708 0.69627909]\n"
     ]
    }
   ],
   "source": [
    "def init_network(): # 权重和偏置的初始化\n",
    "    network = {}\n",
    "    network['W1'] = np.array([[0.1, 0.3, 0.5], [0.2, 0.4, 0.6]])\n",
    "    network['b1'] = np.array([0.1, 0.2, 0.3])\n",
    "    network['W2'] = np.array([[0.1, 0.4], [0.2, 0.5], [0.3, 0.6]])\n",
    "    network['b2'] = np.array([0.1, 0.2])\n",
    "    network['W3'] = np.array([[0.1, 0.3], [0.2, 0.4]])\n",
    "    network['b3'] = np.array([0.1, 0.2])\n",
    "    return network\n",
    "def forward(network, x): # 从输入到输出方向的传递处理\n",
    "    W1, W2, W3 = network['W1'], network['W2'], network['W3']\n",
    "    b1, b2, b3 = network['b1'], network['b2'], network['b3']\n",
    "    a1 = np.dot(x, W1) + b1\n",
    "    z1 = sigmoid(a1)\n",
    "    a2 = np.dot(z1, W2) + b2\n",
    "    z2 = sigmoid(a2)\n",
    "    a3 = np.dot(z2, W3) + b3\n",
    "    y = identity_function(a3)\n",
    "    return y\n",
    "network = init_network()\n",
    "x = np.array([1.0, 0.5])\n",
    "y = forward(network, x)\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "9ef383a8",
   "metadata": {},
   "source": [
    "# 分类问题中使用的softmax函数"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "d58d6aa4",
   "metadata": {},
   "source": [
    "# $$ y_k = \\frac{exp(a_k)}{\\sum_{i=1}^{n} exp(a_i)} $$"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 39,
   "id": "8bd5b76f",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[ 1.34985881 18.17414537 54.59815003]\n"
     ]
    }
   ],
   "source": [
    "a = np.array([0.3, 2.9, 4.0])\n",
    "exp_a = np.exp(a) # 指数函数\n",
    "print(exp_a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 40,
   "id": "8467d6e7",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "74.1221542101633\n"
     ]
    }
   ],
   "source": [
    "sum_exp_a = np.sum(exp_a) # 指数函数的和\n",
    "print(sum_exp_a)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 41,
   "id": "f22df903",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.01821127 0.24519181 0.73659691]\n"
     ]
    }
   ],
   "source": [
    "y = exp_a / sum_exp_a # softmax函数的值\n",
    "print(y)"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "7a42b7d2",
   "metadata": {},
   "outputs": [],
   "source": [
    "def softmax(a):\n",
    "    exp_a = np.exp(a)\n",
    "    sum_exp_a = np.sum(exp_a)\n",
    "    y = exp_a / sum_exp_a\n",
    "    return y"
   ]
  },
  {
   "cell_type": "markdown",
   "id": "019a2dd9",
   "metadata": {},
   "source": [
    "# 溢出问题，加上（或者减去）某个常数并不会改变运算的结果"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 42,
   "id": "251b44e0",
   "metadata": {},
   "outputs": [
    {
     "name": "stderr",
     "output_type": "stream",
     "text": [
      "C:\\Users\\Jwei\\AppData\\Local\\Temp\\ipykernel_18568\\856480931.py:2: RuntimeWarning: overflow encountered in exp\n",
      "  np.exp(a) / np.sum(np.exp(a)) # softmax函数的运算，没有被正确计算\n",
      "C:\\Users\\Jwei\\AppData\\Local\\Temp\\ipykernel_18568\\856480931.py:2: RuntimeWarning: invalid value encountered in divide\n",
      "  np.exp(a) / np.sum(np.exp(a)) # softmax函数的运算，没有被正确计算\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "array([nan, nan, nan])"
      ]
     },
     "execution_count": 42,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([1010, 1000, 990])\n",
    "np.exp(a) / np.sum(np.exp(a)) # softmax函数的运算，没有被正确计算"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 45,
   "id": "ae0db044",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([  0, -10, -20])"
      ]
     },
     "execution_count": 45,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "c = np.max(a) # 1010\n",
    "a - c"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 46,
   "id": "26bc2fe0",
   "metadata": {},
   "outputs": [
    {
     "data": {
      "text/plain": [
       "array([9.99954600e-01, 4.53978686e-05, 2.06106005e-09])"
      ]
     },
     "execution_count": 46,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "np.exp(a - c) / np.sum(np.exp(a - c)) # 指数函数（y = exp(x)）是单调递增函数"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 48,
   "id": "8bde1245",
   "metadata": {},
   "outputs": [],
   "source": [
    "def softmax(a):\n",
    "    c = np.max(a)\n",
    "    exp_a = np.exp(a - c) # 溢出对策\n",
    "    sum_exp_a = np.sum(exp_a)\n",
    "    y = exp_a / sum_exp_a\n",
    "    return y"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": 49,
   "id": "1049f5fb",
   "metadata": {},
   "outputs": [
    {
     "name": "stdout",
     "output_type": "stream",
     "text": [
      "[0.01821127 0.24519181 0.73659691]\n"
     ]
    },
    {
     "data": {
      "text/plain": [
       "1.0"
      ]
     },
     "execution_count": 49,
     "metadata": {},
     "output_type": "execute_result"
    }
   ],
   "source": [
    "a = np.array([0.3, 2.9, 4.0])\n",
    "y = softmax(a)\n",
    "print(y) # 分别表示分类问题中每个类别的概率\n",
    "np.sum(y) # softmax函数的输出值的总和是1"
   ]
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "102f62f3",
   "metadata": {},
   "outputs": [],
   "source": []
  },
  {
   "cell_type": "code",
   "execution_count": null,
   "id": "e69092f8",
   "metadata": {},
   "outputs": [],
   "source": []
  }
 ],
 "metadata": {
  "kernelspec": {
   "display_name": "Python 3 (ipykernel)",
   "language": "python",
   "name": "python3"
  },
  "language_info": {
   "codemirror_mode": {
    "name": "ipython",
    "version": 3
   },
   "file_extension": ".py",
   "mimetype": "text/x-python",
   "name": "python",
   "nbconvert_exporter": "python",
   "pygments_lexer": "ipython3",
   "version": "3.11.4"
  }
 },
 "nbformat": 4,
 "nbformat_minor": 5
}
